<?php

/**
 +----------------------------------------------+
 * PHP Version 5.2.10                           *
 +----------------------------------------------+
 * 功能说明：用于对传入的UBBCODE进行解析
 * 1.getUBBQuenee($type,$content)：解析UBBCODE，生
 * 成待处理的分段UBBCODE队列，队列中的每一个单元
 * 就是需处理的UBBCODE。
 * 2.队列$UBBCodeQuenee的结构：
 * (1).$UBBCodeQuenee[][0]：分段且成对的$UBBCode,
 * 如：
 * $UBBCodeQuenee[][0] = "[b]UBBCode[/b]";
 * (2).$UBBCodeQuenee[][1]：用于匹配现UBBCODE在原始
 * UBBCODE的位置，即可用的正则表达式。
 * 注意：这个生成的正则表达式中，有一个加上去的分
 * 组。这个分组匹配的结果就是用于后面的替换，重要。
 * 如：
 * $UBBCodeQuenee[][0] = "\[b\](UBBCode)\[\/b\]";
 * (3).$UBBCodeQuenee[][2]：记录些种UBBCODE的类型，
 * 如：
 * $UBBCodeQuenee[][0] = "b";
 * 3.getResulthtmlCode()：上面生成的UBBCODE队列进
 * 行进HTML的替换，并返回结果。
 * 注意：这里是同UBBCODE处理工厂的结合处，跟据解
 * 析出来的不同的UBBCODE类型，来动态的创建对应的
 * UBBCODE类，并实例化对像来进行处理。
 +----------------------------------------------+
 * Author    ：九九                             *
 * QQ        ：405494897                        *
 * Email     ：xjiujiu@foxmail.com              *
 * Copyright ：2010/7/24                        *
 +----------------------------------------------+ 
**/

//set CharEncode 
@header("Content-Type:text/html;charset=UTF-8");
@require_once('config/config.php');
@require_once(CLASS_DIR."UBBCode.class.php");       //UBBCode的工厂类
@require_once(CLASS_DIR."UBBFactory.class.php");    //UBBFactory的工厂类

class paserUBBCode{
    private $areaName;              //textarea 的name Id 值,默认 ubbText
    private $className;             //样式class名 ，默认 null
    private $width;                 //textarea 宽度，默认400px
    private $height;                //textarea 高度，默认200px
    private $mode;                  //匹配在正则表达示中有特殊意义的字符，正则数组
    private $replaceRegSymbol;      //给正则表示中的特殊字符加上转义符“\”
    private $totalTimes ;           //记录总的需处理的UBBCODE代码数
    private $regExp;                //用于查找、匹配在原串中UBBCODE代码的正则表达式
    private $UBBCodeQuenee;         //用于存储UBBCODE代码组的队列
    private $resultOne,$resultTwo;  //分别为第一次匹配跟第二次匹配的结果数组
    private $oldUBBCode;            //用于保存最初传入的完整的UBBCODE，也就是整个过程的处理串
    private $UBBCode;               //用于保存当前UBBCODE原始代码段变量。
    private $regExpUBBCode;         //用于保存匹配当前UBBCODE原始代码在原总UUB代码的正则表达式
    private $UBBFactoryName;        //用于保存当前需实例化的UBBCODEFactory类名
    private $objUBBFactory;         //用于保存当前实例化的UBBCodeFactory的对象
    private $objUBBCode;            //用于保存当前处理UBBCODE代码段的UBBCode的对象
    private $type,$content;         //用于保存当前UBBCODE的类型，及UBBCODE之间所夹的内容。
    private $url;                   //用于保存当前数据的链接地址
    private $urlRegExp;             //用于保存当前UBBCODE地址匹配的正则表达式；
    private $startTime,$endTime;    //用于保存解析开始时间，跟解析结束时间
    private $fileFlag;              //用于指示文件是否存在： 不存在（0） or 存在（1） 
    
    /**
    * @name 初始化
    */
    public function __construct($areaName = 'XUBBText',$className = null,$width = 400,$height = 200){
        $this->fileFlag         = 0;
        $this->startTime        = 0;
        $this->endTime          = 0;
        $this->totalTimes       = 0;
        $this->total            = 0;
        $this->areaName         = $areaName;
        $this->className        = $className;
        $this->width            = $width;
        $this->height           = $height;
        $this->type             = null;
        $this->value            = null;
        $this->valueRegExp      = null;
        $this->content          = null;
        $this->UBBCode          = null;
        $this->regExpUBBCode    = null;
        $this->UBBFactoryName   = null;
        $this->objUBBFactory    = null;
        $this->objUBBCode       = null;
        $this->UBBCodeQuenee    = null;
        $this->resultOne        = null;
        $this->resultTwo        = null;
        $this->oldUBBCode       = null; 
        $this->mode             = array(
                                    '/\[/m',
                                    '/\]/m',
                                    '/\(/m',
                                    '/\)/m',
                                    '/\//m',
                                    '/\*/m',
                                    '/\./m',
                                    '/\$/m',
                                    '/\?/m',                    
                                    '/\^/m',
                                    '/\+/m',
                                    '/"/m',
                                                    
                                );
        $this->replaceRegSymbol = array(
                                     '\[',
                                     '\]',
                                     '\(',
                                     '\)',
                                     '\/',
                                     '\*',
                                     '\.',
                                     '\$',
                                     '\?',                    
                                     '\^',
                                     '\+',
                                     '\"',
                                     
                                );        
        $this->regExp           = array(
                                    "/\[([a-z]+)\]([^(\[\\1\])]*)(?:\[\/\\1\])|\[([a-z]+)_(\d+)\]/im",  //0
                                    "/\[([a-z]+)=?([\w:\/\.#]*)\]([^(\[\\1\])]*)(?:\[\/\\1\])|\[([a-z]+)_(\d+)\]/im"  //1
                                );
    }
    
    /**
    * @author 九九 
    * @name 解析UBBCODE代码片段队列
    * 
    * @param $type：当将的UBBCODE的类型
    * @param $content：当前正在处理的UBBCODE代码之间部份。
    * @param $address: 当前正在处理的UBBCODE代码所要链接到的地址
    * @param $UBBCode：存储该段未做处理的UBBCODE代码
    * @param $regExpUBBCode：用于匹配该段UBBCODE在原UBBCODE字符串的正则表达示。
    * @param $UBBFactoryName：待实例的UBBFactory类名
    * 
    * @return String UBBCode结果字符串
    **/
    public function getResultHtmlCode(){        
        $this->oldUBBCode       = $_POST[$this->getTextAreaName()]; 
        $this->startTime = mktime();
        while(@preg_match_all($this->regExp[1],$this->oldUBBCode,$this->resultOne) == true){
            foreach($this->resultOne[0] as $key => $value){
                 if(@preg_match_all($this->regExp[1],$value,$this->resultTwo) == true){
                    //var_dump($this->resultTwo);                         
                    if(empty($this->resultTwo[4][0]) == true){
                        $this->type           = $this->resultTwo[1][0];
                        $this->value          = $this->resultTwo[2][0];
                        $this->content        = $this->resultTwo[3][0];
                        $this->valueRegExp    = empty($this->value)?'':"=".
                                                @preg_replace($this->mode,
                                                $this->replaceRegSymbol,
                                                $this->value
                                                );
                        $this->regExpUBBCode  = @preg_replace($this->mode,$this->replaceRegSymbol,$this->content);
                        $this->regExpUBBCode  = "\[{$this->type}{$this->valueRegExp}\](".
                                                $this->regExpUBBCode.
                                                ")\[\/{$this->type}\]";
                    }else{
                        $this->type       = $this->resultTwo[4][0];
                        $this->content    = $this->resultTwo[5][0];
                        $this->regExpUBBCode  = "\[{$this->type}_(".$this->content.")\]";                       
                    }
                    $this->UBBFactoryName     = self::autoload($this->type."UBBFactory");                    
                    $this->objUBBFactory      = new $this->UBBFactoryName;                                                              
                    $this->objUBBCode         = $this->objUBBFactory->createUBBCodeObj(&$this->oldUBBCode,
                                                                                        $this->value,
                                                                                        $this->content,
                                                                                        $this->regExpUBBCode);
                    if($this->objUBBCode->replaceUBBCode() == true){
                        //echo "OK!<br/>";//write a log
                    }else{
                        echo $this->type."No!<br/>";//write a log
                    }
                    
                    $this->objUBBFactory->__destruct();
                    $this->objUBBCode->__destruct();
                    
                    unset($this->objUBBCode);
                    unset($this->objUBBFactory);  
                                      
                    $this->totalTimes ++;                  
                }
            }            
        }
        $this->endTime  = mktime();       
        return   $this->oldUBBCode;
    }
    
    /**
    * @name 得到总的解析次数
    * 
    * @param $this->totalTimes：总的执行次数；
    * 
    * @return void
    **/
    public function getTotalTimes(){
        return $this->totalTimes;
    }
    
    /**
    * @author 九九 
    * @name 得到总的执行时间
    * 
    * @param $this->startTime：解析开始时间
    * @param $this->endTime：解析结束时间
    * 
    * @return void
    **/
    public function getTotalTime(){
        return $this->endTime - $this->startTime;
    }
    
    /**
     * @author  九九
     * @name    得到当前textarea 的name 属性值
     * @param 	null
     * @return  String name 的属性值
    **/
    public function getTextAreaName(){
        return $this->areaName;
    }
    
    /**
    * @name 输出总的解析次数
    * 
    * @param $this->totalTimes：总的执行次数
    * 
    **/
    public function printTotalTimes(){
        echo "总的执行次数：".$this->totalTimes."<br/>";
    }
    
    /**
    * @author 九九 
    * @name 输出总的解析时间
    * 
    * @param $this->startTime：解析开始时间
    * @param $this->endTime：解析结束时间
    * 
    * @return void
    **/
    public function printTotalTime(){          
        echo "总的时间：";
        echo $this->endTime." - ".$this->startTime."<br/>";
        echo $this->endTime - $this->startTime;
        echo "<br/>";
    } 
    
    /**
    * @author 九九 
    * @name 自动转入调用的类文件
    * 
    * @param $className：被调用的类的文件名；
    * @param $includePath：调用类文件所属的文件夹。
    * @param UUBFACTORY_DIR：UUBFactory子类所在的文件夹
    * @param UUBCODE_DIR：UUBCode子类所在的文件夹
    * 
    * @return void
    **/
    private function autoload($className){
        $factoryFilePath       = UBBFACTORY_DIR.$className.".class.php";
        $codeFilePath          = UBBCODE_DIR.substr($className,0,strpos($className,"UBB"))."UBBCode.class.php";
        if(file_exists($factoryFilePath) == true){
            require_once($factoryFilePath);
            require_once($codeFilePath);
            self::setFileFlag(1);
            return $className;
        }else{
            require_once(UBBFACTORY_DIR.NOUBBFACOTRY_FILE);
            require_once(UBBCODE_DIR.NOUBBCODE_FILE);
            self::setFileFlag(0);
            return NOUBBCODE_CLASSNAME;
        }
        
    }
    
    /**
    * @author 九九
    * @name 设置文件是否存在标识
    * 
    * @param $this->fileFlag 0 or 1
    * 
    * @return void
    **/
    public function setFileFlag($fileFlag){
        if(is_numeric($flagFlag)){
            $this->fileFlag     = $fileFlag;
        }        
    }
    
    /**
    * @author 九九
    * @name 得到文件是否存在的标识
    * 
    * @return void
    **/
    public function getFileFlag(){
        return $this->fileFlag;
    }
    
    /**
     * @author  九九
     * @name    创建UBBCODE TextArea 表单域
     * @param   string $className 样式类名
     * @param 	int $width textarea的宽度
     * @param   int $height textarea 的高度
     * 
     * @return  void
    **/
    public function createUBBCodeArea(){
        echo <<<UBBHTML
        <textarea name="{$this->areaName}" id="{$this->areaName}" style="width: {$this->width}px;height: {$this->height}px;"  class='{$this->className}'></textarea>
        <script language="javascript" type="text/javascript" src="js/UbbEditor.js"></script>
        <script type="text/javascript">
            var ubb = new UbbEditor("{$this->areaName}");                      
            ubb.contentLength = 1000;
            ubb.helpLink = "help/ubb.html";
            ubb.render("fontsize|space|bold|italic|underline|strikethrough|color|space|url|email|image|qq|face|swf|movie|space|left|center|right");
        </script>
UBBHTML;
    }
    
}

?>